#include "AnimManager.h"
	AnimManager::AnimManager(ModelManager* mm,FigureManager* fm,TextureManager* tm)
		:Manager("AnimManager"),
		Component("AnimManager"),
		m_mManager(mm),
		m_fManager(fm),
		m_tManager(tm)
	{
	}

	AnimManager::~AnimManager(void)
	{
		Log();
	}

	void AnimManager::addedToObject()
	{
		requestMessage("LoadAnim",&AnimManager::LoadAnim);
		requestMessage("RenderAnim",&AnimManager::RenderAnim);
	}

	bool AnimManager::ChangeAABB(int32 fid,Sphere s)
	{
		/*FIGURE* tmp=&m_fManager->m_data[fid];
		if(m_fManager->m_data.size()<=fid)
			return false;
		if(tmp->aabb!=NULL)
			delete tmp->aabb;
		tmp->aabb= new AABB(s.min,s.max,s.radius);*/
		return false;
	}

	void AnimManager::LoadAnim(const Message & msg)
	{/*
		int aid=boost::any_cast<int>(msg.p);
		for(vector<FIGURE>::iterator iter=m_fManager->m_data.begin();iter<m_fManager->m_data.end();iter++)
		{
			Model* m=m_mManager->GetModel(iter->mid);
			if(m==NULL)
				SEND_ERR_MSG("Internal Error:Model ID can not been found!");
			int32 anim=0;
			for(uint32 i=0;i<m->header->nAnimations;i++)
			{
				if(m->anims[i].animID==0)
				{
					anim=i;
					break;
				}

			}
			if(!AddObj(iter->id,iter->name,anim))
				SEND_ERR_MSG("Internel Error:Add anim failed!");
			if(ChangeAABB(iter->id,m->anims[anim].boundSphere))
				SEND_ERR_MSG("Internel Error:Change AABB error!");
		}*/
	}

	void AnimManager::RenderAnim(const Message & msg)
	{
		DWORD t=boost::any_cast<DWORD>(msg.p);
		CalcAnim(t);
		CreateVetices();
		RenderData();
		m_fManager->ClearVB();
	}

	HRESULT AnimManager::CreateVetices()
	{
		/*for(vector<ANIMATION>::iterator iter=m_data.begin();
			iter<m_data.end();
			iter++)
		{
			if(iter->vertices==NULL)
				continue;
			Model* m=m_mManager->GetModel(m_fManager->GetMid(iter->fid));
			for(vector<Map>::iterator iter2=m->RenderMap.begin();iter2<m->RenderMap.end();iter2++)
			{
				if(iter->vertices==NULL)
					continue;
				if(!InitMap(&*iter2,m,iter->anim))
				{
					continue;
				}
				LPDIRECT3DVERTEXBUFFER9 vb; // Buffer to hold vertices
				if( FAILED( g_pd3dDevice->CreateVertexBuffer( (iter2->indexCount) * sizeof( CUSTOMVERTEX ),
					D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX,
					D3DPOOL_DEFAULT, &vb, NULL ) ) )
				{
					return E_FAIL;
				}

				CUSTOMVERTEX* pVertices;

				if( FAILED( vb->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
					return E_FAIL;
				for( size_t k = 0,b=iter2->indexStart; k < iter2->indexCount; k++,b++ )
				{
					uint16 a = m->indices[b];
					pVertices[k].position = iter->vertices[a];
					pVertices[k].tu=m->vertices[a].texcoords.x;
					pVertices[k].tv=m->vertices[a].texcoords.y;
				}
				vb->Unlock();
				m_fManager->AddVB(iter->fid,vb,iter2->indexCount/3);
			}

		}*/

		return S_OK;
	}

	
	/*bool AnimManager::InitMap(Map* map,Model* model,int32 anim)
	{
		D3DXVECTOR4 ocol = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
		D3DXVECTOR4 ecol = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
		ModelColor* colors=model->colors;

		//if (m->trans == 1.0f)
		//	return false;

		// emissive colors
		if (map->color!=-1 && colors && colors[map->color].color.uses(0)) 
		{
			D3DXVECTOR3 c;
			c = colors[map->color].color.getValue(0,model->animtime);
			if (colors[map->color].opacity.uses(anim)) 
			{
				ocol.w = colors[map->color].opacity.getValue(anim,model->animtime);
			}


			if (map->unlit) 
			{
				ocol.x = c.x; ocol.y = c.y; ocol.z = c.z;
			} else 
			{
				ocol.x = ocol.y = ocol.z = 0;
			}

			ecol = D3DXVECTOR4(c, ocol.w);
		}

		// opacity
		if (map->opacity!=-1) 
		{

			if (model->transparency && model->transparency[map->opacity].trans.uses(0))
				ocol.w *= model->transparency[map->opacity].trans.getValue(0, model->animtime);


			// exit and return false before affecting the opengl Render state
			if (!((ocol.w > 0) && (map->color==-1 || ecol.w > 0)))
				return false;
			else
				return true;
		}
		return true;
	}*/


	void AnimManager::RenderData()
	{

		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
		// Begin the scene
		// Render the vertex buffer contents
		D3DXMATRIXA16 matWorld;
		int i=0;
		for(vector<FIGURE>::iterator iter=m_fManager->m_data.begin();iter<m_fManager->m_data.end();iter++,i++)
		{
			D3DXMatrixIdentity( &matWorld );
			sendMessage("RenderFigureInWorld",&iter->pos);
			OBJ* o=m_mManager->GetObj(iter->mid);
			TEXTURE* t=m_tManager->GetObj(o->tid);

			g_pd3dDevice->SetTexture( 0,t->tex);

			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

			g_pd3dDevice->SetRenderState(D3DRS_ALPHAREF,(DWORD)0x000000A5);
			g_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
			for(int32 i=0;i<iter->nVB;i++)
			{
				g_pd3dDevice->SetStreamSource( 0, iter->VB[i].pVB, 0, sizeof( CUSTOMVERTEX ) );
				g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
				g_pd3dDevice->DrawPrimitive(  D3DPT_TRIANGLELIST , 0, iter->VB[i].count);
			}

		}
		// End the scene
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	}

	bool AnimManager::AddObj(int32 fid,char* name,int32 anim)
	{
		ANIMATION tmp;
		tmp.id=m_cur++;
		tmp.fid=fid;
		size_t size=strlen(name);
		tmp.name=new char[size+1];
		strcpy_s(tmp.name,size+1,name);
		tmp.anim=anim;
		tmp.vertices=NULL;
		m_data.push_back(tmp);
		ChangeAnim(fid,anim);
		return true;
	}

	void AnimManager::Log()
	{
	}

	void AnimManager::CalcAnim(DWORD time)
	{
		if(m_data.empty())
			return;
		for(vector<ANIMATION>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			int32 mid=m_fManager->GetMid(iter->fid);
			assert(mid!=-1);
			if(iter->vertices!=NULL)
				delete iter->vertices;
			AnimatePreModel(m_mManager->GetModel(mid),iter->anim,&iter->vertices,time);
		}
	}

	void AnimManager::AnimatePreModel(Model* m,size_t anim,D3DXVECTOR3** veritces,DWORD time)
	{
	/*	ModelAnimation* anims=m->anims;
		Bone* bones=m->bones;



		ModelAnimation &a = anims[anim];
		int tmax = (a.timeEnd-a.timeStart);
		if (tmax==0) 
			tmax = 1;

		size_t t=time;
		t %= tmax;
		t += a.timeStart;
		//t = animManager->GetFrame();

		//if(t>=anims[anim].timeEnd)
		//{
		//	t=anims[anim].timeStart;
		//}

		m->animtime=t;
		//animtime=t;
		CalcBones(m,anim, t);

		t+=(anims[anim].timeEnd-anims[anim].timeStart)/1000;

		// transform vertices
		ModelVertex *ov = m->vertices;
		*veritces=new D3DXVECTOR3[m->header->nVertices];
		for (size_t i=0; i<m->header->nVertices; ++i,++ov) 
		{ //,k=0
			D3DXVECTOR3 v(0,0,0), n(0,0,0);

			for (size_t b=0; b<4; b++)
			{
				if (ov->weights[b]>0) 
				{
					D3DXVECTOR3 tv ;
					D3DXVec3TransformCoord(&tv , &ov->pos,&bones[ov->bones[b]].mat);
					v += tv * ((float)ov->weights[b] / 255.0f);
				}
			}
			(*veritces)[i] = v;
		}*/
	}

	void AnimManager::CalcBones(Model* m,size_t anim, size_t time)
	{
		/*Bone* bones=m->bones;
		for (size_t i=0; i<m->header->nBones; i++) {
			bones[i].calc = false;
		}

		for (size_t i=0; i<m->header->nBones; i++) {
			bones[i].calcMatrix(bones, anim, time,true);
		}*/
	}

	bool AnimManager::ChangeAnim(int32 fid, int32 anim)
	{
		for(vector<ANIMATION>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->id==fid)
			{
				iter->anim=anim;
				Model* m=m_mManager->GetModel(m_fManager->GetMid(fid));
			}
		}
		return false;
	}